package com.xquant.trade.utils;


import com.xquant.trade.XppTradeApplication;
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * 此类是利用FreeMark引擎生成word文档
 */
public class WordGenerator {

    private static Configuration configuration = null;
    private static Map<String, Template> allTemplates = null;
    private static Logger logger = LoggerFactory.getLogger(WordGenerator.class);

    static {
        configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding(configuration.getEncoding(Locale.CHINA));
        //指定模板所在的目录
        ClassLoader classLoader = XppTradeApplication.class.getClassLoader();
        URL resource = classLoader.getResource("templates");
        File templatesDir = new File(resource.getPath());
        try {
            configuration.setDirectoryForTemplateLoading(templatesDir);
        } catch (IOException e) {
            e.printStackTrace();
        }
        allTemplates = new HashMap<>();    // Java 7 钻石语法
     /*   try {
            allTemplates.put("temp", configuration.getTemplate("收益凭证估值日报模板(doc).ftl"));
            allTemplates.put("docxTemplate", configuration.getTemplate("收益凭证日报模板.ftl"));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }*/
    }

    private WordGenerator() {
        throw new AssertionError();
    }

    public static File createDoc(Map<?, ?> dataMap, String type) {
        String name = "temp" + (int) (Math.random() * 100000) + ".doc";
        FileOutputStream fileOutputStream = null;
        File f = null;
        Template t = allTemplates.get(type);
        try {
            f = new File(name);
            fileOutputStream = new FileOutputStream(f);
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            Writer w = new OutputStreamWriter(fileOutputStream, configuration.getEncoding(Locale.CHINA));
            t.process(dataMap, w);
            w.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        } finally {
            if (null != fileOutputStream) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return f;
    }

    public static File CreateDocx(FileInputStream fis, Map<?, ?> dataMap, String type) {

        ByteArrayInputStream in = null;
        Template t = allTemplates.get(type);
        try {
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            StringWriter swriter = new StringWriter();
            t.process(dataMap, swriter);
            in = new ByteArrayInputStream(swriter.toString().getBytes(configuration.getEncoding(Locale.CHINA)));
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
        File file = ZipGeneric(in, fis);
        return file;

    }

    //生成docx文件
    public static File ZipGeneric(ByteArrayInputStream in, FileInputStream fis) {
        ZipOutputStream zipout = null;
        File tempDocxFile = null;
        try {
            ClassPathResource classPathResource = new ClassPathResource("\\templates\\收益凭证.zip");
            File docxFile = classPathResource.getFile();
            if (!docxFile.exists()) {
                docxFile.createNewFile();
            }
            ZipFile zipFile = new ZipFile(docxFile);
            Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
            tempDocxFile = new File((int) (Math.random() * 100000) + "temp.docx");
            zipout = new ZipOutputStream(new FileOutputStream(tempDocxFile));
            //开始覆盖文档------------------
            int len = -1;
            byte[] buffer = new byte[1024];

            while (zipEntrys.hasMoreElements()) {
                ZipEntry next = zipEntrys.nextElement();
                InputStream is = zipFile.getInputStream(next);
                if (next.toString().indexOf("media") < 0) {
                    zipout.putNextEntry(new ZipEntry(next.getName()));
                    if ("word/document.xml".equals(next.getName())) {//如果是word/document.xml由我们输入
                        if (in != null) {
                            while ((len = in.read(buffer)) != -1) {
                                zipout.write(buffer, 0, len);
                            }
                            in.close();
                        }
                    } else {
                        while ((len = is.read(buffer)) != -1) {
                            zipout.write(buffer, 0, len);
                        }
                        is.close();
                    }
                } else {
                    //写入图片
                    zipout.putNextEntry(new ZipEntry(next.getName()));
                    if ("word/media/image2.jpeg".equals(next.getName())) {//如果是word/document.xml由我们输入
                        if (fis != null) {
                            while ((len = fis.read(buffer)) != -1) {
                                zipout.write(buffer, 0, len);
                            }
                            in.close();
                        }
                    } else {
                        while ((len = is.read(buffer)) != -1) {
                            zipout.write(buffer, 0, len);
                        }
                        is.close();
                    }
                }
            }

        } catch (Exception e) {
            logger.error("word导出失败:" + e.getStackTrace());
        } finally {
            if (zipout != null) {
                try {
                    zipout.close();
                } catch (IOException e) {
                    logger.error(e.getMessage());

                }
            }
        }
        return tempDocxFile;
    }

    //转换为pdf文件
    public static File PDFGeneric(File docxFile) {
        File output = new File((int) (Math.random() * 100000) + "temp.pdf");

        FileOutputStream fos = null;
        FileInputStream fileInputStream = null;
        XWPFDocument xwpfDocument = null;
        try {
            fileInputStream = new FileInputStream(docxFile);
            fos = new FileOutputStream(output);
            if (docxFile == null) {
                return null;
            }
            xwpfDocument = new XWPFDocument(fileInputStream);
            PdfOptions pdfOptions = PdfOptions.create();
            PdfConverter.getInstance().convert(xwpfDocument, fos, pdfOptions);
            return output;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fileInputStream) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != xwpfDocument) {
                try {
                    xwpfDocument.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != fos) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;

    }
}
